package org.testis.gui.mvc.controller.testdesign;

import org.testis.gui.mvc.controller.*;
import org.testis.gui.mvc.utilities.Operation;
import org.testis.gui.mvc.utilities.OperationExecutor;
import org.testis.gui.mvc.view.testdesign.TreeViewPanel;
import org.testis.utils.StringVerification;
import org.testis.utils.Timer;
import org.testis.utils.tree.MyDefaultMutableTreeNode;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.swing.tree.TreePath;
import org.apache.commons.collections.MultiHashMap;
import org.orm.PersistentException;
import org.orm.PersistentTransaction;
import org.testis.orm.classes.T_test_designtree;
import org.testis.orm.manager.TestisDbPersistentManager;
import org.testis.orm.refinedclasses.*;
import org.testis.utils.middleware.DynamicMap;
import org.testis.utils.middleware.TestDesign;

/**
 *
 * @author Cahit Emir Erel
 */
public class TreeController extends AbstractController implements Draggable,
        OperationExecutor,
        Selectable {

    public static final String NODE_DELETE = "Delete";
    public static final String TREE_LOAD = "LoadTree";
    public static final String TREE_REFRESH = "RefreshTree";
    public static final String TREE_RELOAD = "ReloadTree";
    public static final String SAVE_TREE_PATH = "TreePath";
    public static final String RELOAD_TREE_PATH = "ReloadTreePath";
    public static final String TREE_SAVE = "SaveTree";
    public static final String SHOW_TAB = "ShowTab";
    public static final String HIDE_TAB = "HideTab";
    public static final String SELECT_DESIGN_PART = "SelectedNode";
    public static final String SHOW_PROPERTIES = "Properties";
    public static final String MODIFY_TEST_SUITE = "TestSuiteVisibility";
    public static final String ADD_TEST_SUITE = "TestSuite";
    public static final String COMPARE_MODE_ON = "CompareMode";
    public static final String DESTINATION = "Destination";
    public static final String SOURCE = "Source";
    public static final String CLEAR_SELECTION_PROPERTY = "ClearSelection";
    private MyDefaultMutableTreeNode[] m_selected;
    private MyDefaultMutableTreeNode[] m_notSelected;
    private boolean m_sourceSelected = false;
    private MultiHashMap cloneIdsOfOriginals;
    private HashMap<Integer, Integer> newIdsOfOriginals;
    private String m_lastSearchValue;

    public TreeController() {
        super();
    }

    public void operationRefreshTree() {
        setModelProperty(TREE_REFRESH, true);
    }

    public void operationTreePathChanged(TreePath path) {
        setModelProperty(SAVE_TREE_PATH, path);
    }

    public void operationShowTab(Integer tab) {
        setModelProperty(SHOW_TAB, tab);
    }

    public void operationChangeLastSearch(String searchValue) {
        m_lastSearchValue = searchValue;
    }

    public synchronized void operationHandleSaveClones(SaveAble controller,
            TestDesignTreeNode node,
            HashMap<String, Object> params) {
        Timer t = new Timer();
        t.reset();
        boolean result = true;
        boolean compareParameters = true;
        boolean hasSameRuntimeParams = true;
        if (!node.isClone() && node.isSafeToDelete()) {
            compareParameters = node.compareParameters(params,
                    null);
            if (!compareParameters) {
                boolean isValidSave = controller.isValidSave(params, node);
                if (isValidSave) {
                    result = controller.operationSave(params,
                            node,
                            false);
                }
            } else {
                hasSameRuntimeParams = node.hasSameRunTimeParams(params, null);
                if (!hasSameRuntimeParams) {
                    result = controller.operationSave(params,
                            node,
                            true);
                } else {
                    result = false;
                }
            }
        } // This node is an original with no clones
        else {
            compareParameters = node.compareParameters(params,
                    null);
            if (compareParameters) {
                hasSameRuntimeParams = node.hasSameRunTimeParams(params, null);
                if (!hasSameRuntimeParams) {
                    result = controller.operationSave(params,
                            node,
                            true);
                } else {
                    result = false;
                }
            } else {
                result = showListOfClones(controller,
                        node,
                        params);
            }
        } // This node is a clone or an original that has clones
        t.print(" operationHandleSaveClones  in ms:");
        if (result) {
            operationRefreshTree();
        } else if (!compareParameters && !result) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid save...",
                    "ERROR");
        } else if (!hasSameRuntimeParams && !result) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid save...",
                    "ERROR");
        }
    }

    public synchronized void operationHandleAdd(Addable controller,
            TestDesignTreeNode node,
            HashMap<String, Object> params) throws PersistentException {
        boolean result = false;
        Timer t = new Timer();
        t.reset();
        if (node == null || (!node.isClone() && node.isSafeToDelete())) {
            boolean isValidAdd = controller.isValidAdd(params, node);
            if (isValidAdd) {
                TestDesignTreeNode adddedNode = null;
                if (node == null)//for new test suite
                {
                    adddedNode = controller.operationAddObject(params,
                            node, 0);
                } else {
                    adddedNode = controller.operationAddObject(params,
                            node, node.getChildren().length);
                }
                if (adddedNode != null) {
                    result = true;
                }
            }

        } // This node is an original with no clones
        else {
            result = showListOfAdds(controller,
                    node,
                    params);
        } // This node is a clone or an original that has clones
        t.print(" operationHandleAdd  in ms:");
        if (result) {
            reloadAllTrees();
        } else {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid Add...",
                    "ERROR");
        }
    }

    public boolean safeDeleteWithTransaction(MyDefaultMutableTreeNode deleteNode, boolean startTransaction) {
        PersistentTransaction t = null;
        try {
            if (startTransaction) {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();
            }
            try {
                OperationResultObject result = new OperationResultObject(
                        true);
                operationDeleteTreeNodeInternal((TestDesignTreeNode) deleteNode.getUserObject(),
                        result);
                if (result.isResult() && startTransaction) {
                    t.commit();
                    return true;
                } else if (startTransaction) {
                    try {
                        t.rollback();
                    } catch (PersistentException ex1) {
                        ex1.printStackTrace();
                    }
                    operationGenerateErrorMessage("Can not delete node with node data: "
                            + deleteNode.toString(),
                            "Error!");
                } else {
                    return true;
                }
            } catch (Exception ex) {
                try {
                    if (t != null) {
                        t.rollback();
                    }
                } catch (PersistentException ex1) {
                    ex1.printStackTrace();

                }
                ex.printStackTrace();
                operationGenerateErrorMessage("Can not delete node with node data: "
                        + deleteNode.toString(),
                        "Error!");
            }
        } catch (Exception ex) {

            operationGenerateErrorMessage("Can not start transaction "
                    + deleteNode.toString(),
                    "Error!");
            ex.printStackTrace();
        }
        return false;
    }

    public synchronized void operationHandleDelete(
            MyDefaultMutableTreeNode deleteNode) {
        Timer t = new Timer();
        t.reset();
        boolean result = false;
        TestDesignTreeNode node =
                (TestDesignTreeNode) deleteNode.getUserObject();
        if (node == null || (!node.isClone() && node.isSafeToDelete())) {
            result = safeDeleteWithTransaction(deleteNode, true);
        } // This node is an original with no clones
        else {
            result = showListOfDeletes(deleteNode);
        } // This node is a clone or an original that has clones
        t.print(" operationHandleDelete  in ms:");

        reloadAllTrees();
        if (!result) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid delete...",
                    "ERROR");
        }

    }

    public boolean safeCloneWithTransaction(TestDesignTreeNode clone,
            TestDesignTreeNode targetNode, int childIndex,
            boolean startTransaction, boolean processSelectedObjects) {

        OperationResultObject result = new OperationResultObject(
                true);
        PersistentTransaction t = null;


        try {
            if (startTransaction) {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();


            }
            operationPasteCloneInternal(clone,
                    targetNode,
                    result, childIndex, processSelectedObjects);


            if (result.isResult() && startTransaction) {
                t.commit();


            }
        } catch (Exception ex) {
            result.setResult(false);


            if (t != null) {
                try {
                    t.rollback();


                } catch (PersistentException ex1) {
                    ex1.printStackTrace();


                }
            }
            ex.printStackTrace();


        }
        return result.isResult();


    }

    public synchronized void operationHandlePasteClone(TestDesignTreeNode clone,
            MyDefaultMutableTreeNode targetNode, boolean processSelectedObjects) {
        if (!clone.isSelected() && processSelectedObjects) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("No node selected for copy...",
                    "ERROR");


            return;


        }
        Timer t = new Timer();
        t.reset();


        boolean result = false;
        TestDesignTreeNode node =
                (TestDesignTreeNode) targetNode.getUserObject();


        if (node == null || (!node.isClone() && node.isSafeToDelete())) {
            result = safeCloneWithTransaction(clone,
                    (TestDesignTreeNode) targetNode.getUserObject(), targetNode.getChildCount(), true, processSelectedObjects);


        } // This node is an original with no clones
        else {
            result = showListOfPasteClone(clone,
                    targetNode, processSelectedObjects);


        } // This node is a clone or an original that has clones
        t.print(" operationHandlePasteClone  in ms:");


        if (result) {
            reloadAllTrees();


        } else {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid paste clone...",
                    "ERROR");


        }

    }

    public boolean safeCopyWithTransaction(TestDesignTreeNode copy,
            TestDesignTreeNode targetNode,
            boolean oneToToneCopy, int childIndex,
            boolean startTransaction, boolean processSelectedObjects) {

        OperationResultObject result = new OperationResultObject(
                true);
        PersistentTransaction t = null;


        try {
            if (startTransaction) {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();


            }
            operationPasteCopyInternal(copy,
                    targetNode,
                    oneToToneCopy,
                    result, childIndex, processSelectedObjects);


            if (result.isResult() && startTransaction) {
                if (oneToToneCopy) {
                    Set keySet = newIdsOfOriginals.keySet();
                    Iterator<Integer> setIter = keySet.iterator();
                    while (setIter.hasNext()) {
                        Integer oldOriginalId = setIter.next();
                        Integer newOriginalId = newIdsOfOriginals.get(oldOriginalId);
                        TestDesignTreeNode originalNode = TestDesignTreeNode.getNodeById(newOriginalId);
                        List list = (List) cloneIdsOfOriginals.get(oldOriginalId);
                        if (list != null) {
                            for (int i = 0; i < list.size(); i++) {
                                Integer newCloneId = (Integer) list.get(i);
                                TestDesignTreeNode node = TestDesignTreeNode.getNodeById(newCloneId);
                                node.getReference().getTreeReference().setClone(originalNode.getReference().getTreeReference());
                                node.getReference().getTreeReference().save();
                                //refresh node
                                TestDesignTreeNode.getNode(node.getReference(), originalNode.getObject());
                                //save original
                                originalNode.getReference().getTreeReference().save();
                            }
                        }
                    }
                }
                t.commit();
            }
        } catch (Exception ex) {
            result.setResult(false);


            if (t != null) {
                try {
                    t.rollback();


                } catch (PersistentException ex1) {
                    ex1.printStackTrace();


                }
            }
            ex.printStackTrace();


        }
        return result.isResult();



    }

    public synchronized void operationHandlePasteCut(TestDesignTreeNode cutNode,
            MyDefaultMutableTreeNode parentNode) {
        TestDesignTreeNode targetNode = (TestDesignTreeNode) parentNode.getUserObject();
        String typeName = cutNode.getTypeName();
        String targetTypeName = targetNode.getTypeName();
        if (targetNode.getId() == cutNode.getParent().getId()) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Can not paste to same place...",
                    "ERROR");

            return;
        }
        if (typeName.equals("DataObject")) {
            String targetModuleName = TestDesign.getTestStepModuleTypeName(targetNode.getReference());
            String targetActionName = TestDesign.getTestStepActionName(targetNode.getReference());
            String moduleName = TestDesign.getTestStepModuleTypeName(cutNode.getParent().getReference());
            String actionName = TestDesign.getTestStepActionName(cutNode.getParent().getReference());
            if (!moduleName.equals(targetModuleName)
                    || !actionName.equals(targetActionName)) {
                TestDesignControllerList.newInstance().getTreeController().
                        operationGenerateErrorMessage("Target TestStep module/action is different...",
                        "ERROR");
                return;
            }
        }
        Timer t = new Timer();
        t.reset();
        boolean result = TestDesign.newInstance().moveCutObject(cutNode, targetNode);
        if (result) {
            reloadAllTrees();
        } else {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid paste cut...",
                    "ERROR");
        }
        t.print(" operationHandleCut  in ms:");
    }

    public synchronized void operationHandlePasteCopy(TestDesignTreeNode copy,
            MyDefaultMutableTreeNode targetNode,
            boolean oneToToneCopy, boolean processSelectedObjects) throws PersistentException {
        if (!copy.isSelected() && processSelectedObjects) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("No node selected for copy...",
                    "ERROR");
            return;
        }
        Timer t = new Timer();
        t.reset();


        boolean result = false;

        TestDesignTreeNode node =
                (TestDesignTreeNode) targetNode.getUserObject();

        if (oneToToneCopy) {
            cloneIdsOfOriginals = new MultiHashMap();
            newIdsOfOriginals = new HashMap<Integer, Integer>();
        }
        if (node == null || (!node.isClone() && node.isSafeToDelete())) {
            if (copy.getTypeName().equals("TestSuite") && copy.getChildrenCount() > 0) {
                int index = 0;
                for (index = 0; index < copy.getChildrenCount(); index++) {
                    TestDesignTreeNode copyChild = copy.getChild(index);
                    result = safeCopyWithTransaction(copyChild,
                            (TestDesignTreeNode) targetNode.getUserObject(),
                            oneToToneCopy, targetNode.getChildCount(), true, processSelectedObjects);
                    if (!result) {
                        if (index > 0) {
                            reloadAllTrees();
                        }
                        TestDesignControllerList.newInstance().getTreeController().
                                operationGenerateErrorMessage("Can not  copy:" + copyChild.getName(),
                                "ERROR");
                        break;
                    }
                }
                if (oneToToneCopy && index > 0) {
                    PersistentTransaction transcation = null;
                    try {
                        transcation = TestisDbPersistentManager.instance().
                                getSession().beginTransaction();
                        Set keySet = newIdsOfOriginals.keySet();
                        Iterator<Integer> setIter = keySet.iterator();
                        while (setIter.hasNext()) {
                            Integer oldOriginalId = setIter.next();
                            Integer newOriginalId = newIdsOfOriginals.get(oldOriginalId);
                            TestDesignTreeNode originalNode = TestDesignTreeNode.getNodeById(newOriginalId);
                            List list = (List) cloneIdsOfOriginals.get(oldOriginalId);
                            if (list != null) {
                                for (int i = 0; i < list.size(); i++) {
                                    Integer newCloneId = (Integer) list.get(i);
                                    TestDesignTreeNode cloneNode = TestDesignTreeNode.getNodeById(newCloneId);
                                    cloneNode.getReference().getTreeReference().setClone(originalNode.getReference().getTreeReference());
                                    cloneNode.getReference().getTreeReference().save();
                                    TestDesignTreeNode.getNode(cloneNode.getReference(), originalNode.getObject());
                                    originalNode.getReference().getTreeReference().save();
                                }
                            }
                        }
                        transcation.commit();
                    } catch (PersistentException ex) {
                        if (transcation != null) {
                            transcation.rollback();
                        }
                        ex.printStackTrace();
                    }
                }
            } else {
                result = safeCopyWithTransaction(copy,
                        (TestDesignTreeNode) targetNode.getUserObject(),
                        oneToToneCopy, targetNode.getChildCount(), true, processSelectedObjects);
            }


        } // This node is an original with no clones
        else {
            result = showListOfPasteCopy(copy,
                    targetNode,
                    oneToToneCopy, processSelectedObjects);


        } // This node is a clone or an original that has clones
        t.print(" operationHandlePasteCopy  in ms:");


        if (result) {
            reloadAllTrees();


        } else {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Invalid paste copy...",
                    "ERROR");


        }
    }

    @Override
    public MyDefaultMutableTreeNode[] getSelected() {
        return m_selected;


    }

    @Override
    public void setSelected(MyDefaultMutableTreeNode[] selected) {
        m_selected = selected;


    }

    public void operationReloadTree() {
        MyDefaultMutableTreeNode selectedNode = getSelectedMutableTreeNode();
        TestDesignTreeNode object =
                (TestDesignTreeNode) selectedNode.getUserObject();


        while (!(object.getObject() instanceof TestSuiteRefined)) {
            selectedNode = selectedNode.getParent();
            object =
                    (TestDesignTreeNode) selectedNode.getUserObject();


        }


        operationReloadTree(selectedNode,
                object.getName());


    }

    public void operationReloadTree(String name) {
        MyDefaultMutableTreeNode child;
        MyDefaultMutableTreeNode root = TestDesignControllerList.newInstance().
                getJDesignTreeRoot();


        for (int i = 0; i
                < root.getChildCount(); i++) {
            child = root.getChildAt(i);


            if (((TestDesignTreeNode) child.getUserObject()).getName().equals(
                    name)) {
                operationReloadTree(child,
                        name);


                return;


            }
        }
    }

    public void operationReloadTree(MyDefaultMutableTreeNode target) {
        operationReloadTree(target,
                ((TestDesignTreeNode) target.getUserObject()).getName());


    }

    public void reloadAllTrees() {
        String[] names = getLoadedTrees();
        for (int i = 0; i
                < names.length; i++) {
            operationReloadTree(names[i]);
        }
    }

    public void operationReloadTree(MyDefaultMutableTreeNode target,
            String name) {
        operationCloseTree(target);
        operationLoadTreeFromDb(
                name);
        setModelProperty(
                TREE_RELOAD,
                true);
        LinkedList<TreePath> currentTreePaths =
                (LinkedList<TreePath>) getModelProperty(SAVE_TREE_PATH);


        for (int i = 0; i
                < currentTreePaths.size(); i++) {
            TreePath path = currentTreePaths.get(i);
            String rootNameForPath = path.getPath()[1].toString();


            if (name.trim().equals(rootNameForPath.trim())) {
                setModelProperty(RELOAD_TREE_PATH,
                        path);
                break;
            }
        }
    }

    private boolean convertCloneOfGhostToOriginal(TestDesignTreeNode clone,
            TestDesignTreeNode ghost) {
        return TestDesign.newInstance().convertCloneOfGhostToOriginal(
                clone.getReference().getTreeReference(),
                ghost.getReference().getTreeReference());
    }

    private synchronized Integer[] createCloneList(TestDesignTreeNode node,
            LinkedList<TestDesignTreeNode> nodes) {
        Integer defaultSelected = null;
        TestDesignTreeNode originalNode;
        int nodeId = node.getId();
        if (node.isClone()) {
            originalNode = TestDesignTreeNode.getNode(TestDesignTreeRefined.getDesignTree(node.getReference().getTreeReference().
                    getClone()));
        } else {
            originalNode = node;
        }
        System.out.println("NO OF CLONES IS " + originalNode.getClones().length);
        for (int i = 0; i
                < originalNode.getClones().length; i++) {
            nodes.add(TestDesignTreeNode.getNode(originalNode.getClones()[i]));
        }
        for (int i = 0; i
                < nodes.size(); i++) {
            if (nodes.get(i).getId() == nodeId) {
                defaultSelected = new Integer(i);
            }
        }
        if (originalNode.isGhost()) {
            convertCloneOfGhostToOriginal(nodes.remove(
                    defaultSelected.intValue()),
                    originalNode);
            originalNode =
                    TestDesignTreeNode.getNode(originalNode.getReference());
            nodes.add(originalNode);
            defaultSelected =
                    new Integer(nodes.size() - 1);
        } else {
            nodes.add(originalNode);
            if (defaultSelected == null) {
                defaultSelected = new Integer(nodes.size() - 1);
            }
        }
        return new Integer[]{defaultSelected};
    }

    private void startTestDesignSelecter(LinkedList<TestDesignTreeNode> list,
            Integer[] defaultSelected,
            TestDesignTreeNode clickedNode,
            String title,
            boolean addchild) {
        TestDesignControllerList.newInstance().getSelectController().
                startTestDesignSelecter(this,
                list,
                defaultSelected,
                clickedNode,
                title,
                addchild);
    }

    private synchronized boolean showListOfDeletes(
            MyDefaultMutableTreeNode deleteNode) {
        LinkedList<MyDefaultMutableTreeNode> changeNodes =
                new LinkedList<MyDefaultMutableTreeNode>();
        LinkedList<TestDesignTreeNode> nodes =
                new LinkedList<TestDesignTreeNode>();
        try {
            Integer[] defaults = createCloneList(
                    (TestDesignTreeNode) deleteNode.getUserObject(),
                    nodes);
            startTestDesignSelecter(
                    nodes,
                    defaults, (TestDesignTreeNode) deleteNode.getUserObject(),
                    "Which ones to delete?",
                    false);
            MyDefaultMutableTreeNode originalNode = null;


            if (getSelected() != null && getSelected().length > 0) {
                for (int i = 0; i
                        < getSelected().length; i++) {
                    TestDesignTreeNode node = (TestDesignTreeNode) getSelected()[i].getUserObject();


                    if (!node.isClone()) {
                        originalNode = getSelected()[i];


                    }
                    changeNodes.add(getSelected()[i]);
                }
            } else {
                // User wants to change nothing! Just exit!
                return false;


            }
            boolean result = true;
            PersistentTransaction t = null;


            try {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();



                for (int i = 0; i
                        < changeNodes.size(); i++) {
                    TestDesignTreeNode node = (TestDesignTreeNode) getSelected()[i].getUserObject();
                    if (node.isClone()) {
                        result = safeDeleteWithTransaction(changeNodes.get(i), false);
                        if (!result) {
                            break;
                        }
                    }
                }
                if (originalNode != null) {
                    result = safeDeleteWithTransaction(originalNode, false);
                }
                if (result) {
                    t.commit();
                } else {
                    t.rollback();
                }
            } catch (Exception ex) {
                if (t != null) {
                    try {
                        t.rollback();
                    } catch (PersistentException ex1) {
                        ex1.printStackTrace();
                    }
                }
                ex.printStackTrace();
            }
        } finally {
            setSelected(null);
            setNotSelected(
                    null);
        }
        return true;
    }

    private synchronized boolean showListOfAdds(Addable controller,
            TestDesignTreeNode node,
            HashMap<String, Object> params) throws PersistentException {
        LinkedList<MyDefaultMutableTreeNode> changeNodes =
                new LinkedList<MyDefaultMutableTreeNode>();
        LinkedList<TestDesignTreeNode> nodes =
                new LinkedList<TestDesignTreeNode>();
        try {
            Integer[] defaults = createCloneList(node,
                    nodes);
            startTestDesignSelecter(
                    nodes,
                    defaults, node,
                    "Which ones to add?",
                    true);
            if (getSelected() != null && getSelected().length > 0) {
                for (int i = 0; i
                        < getSelected().length; i++) {
                    changeNodes.add(getSelected()[i]);
                }
            } else {
                // User wants to change nothing! Just exit!
                return false;
            }
            MyDefaultMutableTreeNode copyTarget;
            TestDesignTreeNode copyParentNode;
            TestDesignTreeNode original = null;
            int j = 0;
            for (int k = 1; k
                    < changeNodes.size(); k++) {//find original parent node
                copyTarget = changeNodes.get(k);
                copyParentNode =
                        (TestDesignTreeNode) copyTarget.getParent().
                        getUserObject();
                if (copyParentNode.getReference().getTreeReference().getClone()
                        == null) {
                    j = k;
                }
            }
            copyTarget = changeNodes.get(j);
            copyParentNode = (TestDesignTreeNode) copyTarget.getParent().getUserObject();
            int originalAddIndex = copyTarget.getParent().getIndex(copyTarget);
            if (copyParentNode.isGhost()) {
                System.err.println(
                        "TRYING TO PASTE INTO A GHOST! THIS SHOULD NEVER HAPPEN!");
                return false;
            }
            boolean isValidAdd = controller.isValidAdd(params, copyParentNode);
            if (isValidAdd) {
                original = controller.operationAddObject(params, copyParentNode, originalAddIndex);
            }
            if (original == null) {
                return false;
            }
            changeNodes.remove(j);
            PersistentTransaction t = null;
            try {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();
                for (int i = 0; i
                        < changeNodes.size(); i++) {
                    copyTarget = changeNodes.get(i);
                    copyParentNode = (TestDesignTreeNode) copyTarget.getParent().getUserObject();
                    int addIndex = copyTarget.getParent().getIndex(copyTarget);
                    if (addIndex == -1) {
                        addIndex = originalAddIndex;
                    }
                    TestDesignTreeNode temp = TestDesign.newInstance().
                            operationPasteClone(original,
                            (TestDesignTreeNode) changeNodes.get(i).
                            getParent().getUserObject(), addIndex);
                    if (temp == null) {
                        System.out.println(" --- CLONE OPERATION --- ");
                        System.out.println("Source: " + original);
                        System.out.println("Target: " + changeNodes.get(i).getParent().
                                getUserObject());
                        System.out.println("CLONE FAILED!");
                        continue;
                    }
                }
                t.commit();
            } catch (Exception ex) {
                if (t != null) {
                    try {
                        t.rollback();
                    } catch (PersistentException ex1) {
                        ex1.printStackTrace();
                    }
                }
                ex.printStackTrace();
            }
        } finally {
            setSelected(null);
            setNotSelected(null);
        }
        return true;
    }

    private synchronized boolean showListOfPasteCopy(TestDesignTreeNode copy,
            MyDefaultMutableTreeNode targetNode,
            boolean oneToToneCopy, boolean processSelectedObjects) throws PersistentException {
        LinkedList<MyDefaultMutableTreeNode> changeNodes =
                new LinkedList<MyDefaultMutableTreeNode>();
        LinkedList<TestDesignTreeNode> nodes =
                new LinkedList<TestDesignTreeNode>();
        try {
            Integer[] defaults = createCloneList(
                    (TestDesignTreeNode) targetNode.getUserObject(),
                    nodes);
            startTestDesignSelecter(
                    nodes,
                    defaults, (TestDesignTreeNode) targetNode.getUserObject(),
                    "Which ones to add?",
                    true);
            if (getSelected() != null && getSelected().length > 0) {
                for (int i = 0; i
                        < getSelected().length; i++) {
                    changeNodes.add(getSelected()[i]);
                }
            } else {
                // User wants to change nothing! Just exit!
                return false;
            }
            MyDefaultMutableTreeNode copyTarget;
            int addIndex;
            int indexOfOriginal = 0;
            for (int i = 0; i
                    < changeNodes.size(); i++) {
                TestDesignTreeNode parentNode = (TestDesignTreeNode) changeNodes.get(i).getParent().getUserObject();
                if (!parentNode.isClone()) {
                    indexOfOriginal = i;
                    break;
                }
            }
            if (indexOfOriginal != 0) {
                MyDefaultMutableTreeNode selectedOriginal = changeNodes.get(indexOfOriginal);
                changeNodes.remove(indexOfOriginal);
                changeNodes.add(0, selectedOriginal);
            }
            PersistentTransaction t = null;
            try {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();
                int originalAddIndex = 0;
                for (int i = 0; i
                        < changeNodes.size(); i++) {
                    copyTarget = changeNodes.get(i);
                    addIndex = copyTarget.getParent().getIndex(copyTarget);
                    if (addIndex < 0) {
                        addIndex = originalAddIndex;
                    }
                    if (i == 0) {
                        originalAddIndex = addIndex;
                        if (!safeCopyWithTransaction(copy, (TestDesignTreeNode) copyTarget.getParent().getUserObject(), oneToToneCopy, addIndex, false, processSelectedObjects)) {
                            System.out.println(" --- COPY OPERATION --- ");
                            System.out.println("Source: " + copy);
                            System.out.println("Target: " + changeNodes.get(i).getParent().
                                    getUserObject());
                            System.out.println("COPY FAILED!");
                            continue;
                        } else {
                            TestDesignTreeNode parentNode = (TestDesignTreeNode) copyTarget.getParent().getUserObject();
                            TestDesignTreeNode[] childNodes = parentNode.getChildren();
                            if (copy.getTypeName().equals("PreConditionCase")) {
                                copy = childNodes[0];
                            } else if (copy.getTypeName().equals("PostConditionCase")) {
                                copy = childNodes[childNodes.length - 1];
                            } else {
                                copy = childNodes[addIndex];
                                if (copy.getTypeName().equals("PreConditionCase")) {
                                    addIndex++;
                                } else if (copy.getTypeName().equals("PostConditionCase")) {
                                    addIndex--;
                                }
                                copy = childNodes[addIndex];
                            }
                        }
                    } else {
                        if (!safeCloneWithTransaction(copy, (TestDesignTreeNode) copyTarget.getParent().getUserObject(), addIndex, false, processSelectedObjects)) {
                            System.out.println(" --- CLONE OPERATION --- ");
                            System.out.println("Source: " + copy);
                            System.out.println("Target: " + changeNodes.get(i).getParent().
                                    getUserObject());
                            System.out.println("CLONE FAILED!");
                            continue;
                        }
                    }
                }
                t.commit();
            } catch (Exception ex) {
                if (t != null) {
                    try {
                        t.rollback();
                    } catch (PersistentException ex1) {
                        ex1.printStackTrace();
                    }
                }
                ex.printStackTrace();
            }
        } finally {
            setSelected(null);
            setNotSelected(
                    null);
        }
        return true;
    }

    private synchronized boolean showListOfPasteClone(TestDesignTreeNode clone,
            MyDefaultMutableTreeNode targetNode, boolean processSelectedObjects) {

        LinkedList<MyDefaultMutableTreeNode> changeNodes =
                new LinkedList<MyDefaultMutableTreeNode>();
        LinkedList<TestDesignTreeNode> nodes =
                new LinkedList<TestDesignTreeNode>();


        try {
            Integer[] defaults = createCloneList(
                    (TestDesignTreeNode) targetNode.getUserObject(),
                    nodes);
            startTestDesignSelecter(
                    nodes,
                    defaults, (TestDesignTreeNode) targetNode.getUserObject(),
                    "Which ones to add?",
                    true);


            if (getSelected() != null && getSelected().length > 0) {
                for (int i = 0; i
                        < getSelected().length; i++) {
                    changeNodes.add(getSelected()[i]);


                }
            } else {
                // User wants to change nothing! Just exit!
                return false;


            }

            MyDefaultMutableTreeNode copyTarget;


            int addIndex;


            int indexOfOriginal = 0;


            for (int i = 0; i
                    < changeNodes.size(); i++) {
                TestDesignTreeNode parentNode = (TestDesignTreeNode) changeNodes.get(i).getParent().getUserObject();


                if (!parentNode.isClone()) {
                    indexOfOriginal = i;


                    break;


                }
            }
            if (indexOfOriginal != 0) {
                MyDefaultMutableTreeNode selectedOriginal = changeNodes.get(indexOfOriginal);
                changeNodes.remove(indexOfOriginal);
                changeNodes.add(0, selectedOriginal);


            }
            PersistentTransaction t = null;


            try {
                t = TestisDbPersistentManager.instance().
                        getSession().beginTransaction();


                int originalAddIndex = 0;


                for (int i = 0; i
                        < changeNodes.size(); i++) {
                    copyTarget = changeNodes.get(i);
                    addIndex = copyTarget.getParent().getIndex(copyTarget);


                    if (addIndex < 0) {
                        addIndex = originalAddIndex;


                    }
                    if (i == 0) {
                        originalAddIndex = addIndex;


                    }
                    if (!safeCloneWithTransaction(clone, (TestDesignTreeNode) copyTarget.getParent().getUserObject(), addIndex, false, processSelectedObjects)) {
                        System.out.println(" --- CLONE OPERATION --- ");
                        System.out.println("Source: " + clone);
                        System.out.println("Target: " + changeNodes.get(i).getParent().
                                getUserObject());
                        System.out.println("CLONE FAILED!");


                        continue;


                    }
                }
                t.commit();


            } catch (Exception ex) {
                if (t != null) {
                    try {
                        t.rollback();


                    } catch (PersistentException ex1) {
                        ex1.printStackTrace();


                    }
                }
                ex.printStackTrace();


            }
        } finally {
            setSelected(null);
            setNotSelected(
                    null);


        }
        return true;


    }

    private TestDesignTreeNode getTestPlanOfNode(TestDesignTreeNode node) {
        while (!(node.getObject() instanceof TestPlanRefined)) {
            node = node.getParent();


        }
        return node;


    }

    private synchronized boolean showListOfClones(SaveAble controller,
            TestDesignTreeNode node,
            HashMap<String, Object> params) {
        LinkedList<MyDefaultMutableTreeNode> changeNodes =
                new LinkedList<MyDefaultMutableTreeNode>();
        LinkedList<MyDefaultMutableTreeNode> keepNodes =
                new LinkedList<MyDefaultMutableTreeNode>();
        LinkedList<TestDesignTreeNode> nodes =
                new LinkedList<TestDesignTreeNode>();


        try {
            Integer[] defaults = createCloneList(node,
                    nodes);
            startTestDesignSelecter(
                    nodes,
                    defaults, node,
                    "Which ones to change?",
                    false);


            boolean changeAll;


            boolean originalChanged = false;
            TestDesignTreeNode originalNode = null;
            TestDesignTreeNode temp;




            if (getSelected() != null && getSelected().length > 0) {
                for (int i = 0; i
                        < getSelected().length; i++) {
                    changeNodes.add(getSelected()[i]);
                    temp = (TestDesignTreeNode) getSelected()[i].getUserObject();


                    if (!temp.isClone()) {
                        originalChanged = true;
                        originalNode = temp;


                    }
                }
                if (changeNodes.size() == nodes.size()) {
                    changeAll = true;


                } else {
                    changeAll = false;


                    if (getNotSelected() != null) {
                        for (int i = 0; i
                                < getNotSelected().length; i++) {
                            keepNodes.add(getNotSelected()[i]);
                            temp = (TestDesignTreeNode) getNotSelected()[i].getUserObject();


                            if (!temp.isClone()) {
                                originalNode = temp;


                            }


                        }
                    }
                }
            } else {
                reloadAllTrees();
                // User wants to change nothing! Just exit!
                return false;


            }

            if (changeAll) {
                boolean isValidSave = controller.isValidSave(params, originalNode);


                if (isValidSave) {
                    return controller.operationSave(params,
                            originalNode,
                            false);


                } else {
                    return false;


                }
            } else {
                if (originalChanged) {
                    boolean isValidSave = controller.isValidSave(params, originalNode);


                    if (!isValidSave) {
                        return false;


                    }
                    PersistentTransaction t = null;


                    boolean isChildsSaved = false;


                    try {
                        t = TestisDbPersistentManager.instance().
                                getSession().beginTransaction();
                        TestDesignTreeNode originalNodeTestPlan = getTestPlanOfNode(originalNode);
                        TestDesignTreeNode keepNodesOriginalNode = null;


                        int indexOfKeepNode = 0;


                        for (int i = 0; i
                                < keepNodes.size(); i++) {
                            TestDesignTreeNode tempNodeTestPlan = getTestPlanOfNode((TestDesignTreeNode) keepNodes.get(i).getUserObject());


                            if (tempNodeTestPlan.getReference().getId() == originalNodeTestPlan.getReference().getId()) {
                                indexOfKeepNode = i;
                                keepNodesOriginalNode = (TestDesignTreeNode) keepNodes.get(i).getUserObject();


                                break;


                            }
                        }
                        if (keepNodesOriginalNode != null) {
                            keepNodesOriginalNode.convertToOriginal(originalNode.getReference());
                            DesignPart objectCopy = originalNode.getObject().createRefinedDatabaseCopy();


                            int elementId = objectCopy.getReference().getId();
                            keepNodesOriginalNode.getReference().getTreeReference().setElementId(elementId);
                            keepNodesOriginalNode.setObject(objectCopy);
                            keepNodesOriginalNode.getReference().getTreeReference().save();
                            keepNodes.remove(indexOfKeepNode);


                            for (int i = 0; i
                                    < keepNodes.size(); i++) {
                                TestDesignTreeNode tmp = (TestDesignTreeNode) keepNodes.get(i).getUserObject();
                                tmp.getReference().getTreeReference().setClone(
                                        keepNodesOriginalNode.getReference().getTreeReference());
                                tmp.getReference().getTreeReference().save();
                                tmp = TestDesignTreeNode.getNode(tmp.getReference(), objectCopy);


                            }

                        } else {//all other clones must be original. because they are on other test plans
                            for (int i = 0; i
                                    < keepNodes.size(); i++) {
                                TestDesignTreeNode keepNode = (TestDesignTreeNode) keepNodes.get(i).getUserObject();
                                keepNode.convertToOriginal(originalNode.getReference());
                                DesignPart objectCopy = originalNode.getObject().createRefinedDatabaseCopy();


                                int elementId = objectCopy.getReference().getId();
                                keepNode.getReference().getTreeReference().setElementId(elementId);
                                keepNode.setObject(objectCopy);
                                keepNode.getReference().getTreeReference().save();
                                keepNode = TestDesignTreeNode.getNode(keepNode.getReference(), objectCopy);


                            }
                        }
                        t.commit();
                        isChildsSaved = true;



                    } catch (Exception ex) {
                        if (t != null) {
                            try {
                                t.rollback();


                            } catch (PersistentException ex1) {
                                ex1.printStackTrace();


                            }
                        }
                        ex.printStackTrace();


                    }
                    if (isChildsSaved) {
                        return controller.operationSave(params,
                                originalNode,
                                false);


                    }
                } else {
                    int indexOfChangeNodesOriginal = 0;
                    TestDesignTreeNode changeNodesOriginalNode = (TestDesignTreeNode) changeNodes.get(indexOfChangeNodesOriginal).getUserObject();


                    boolean isValidSave = controller.isValidSave(params, changeNodesOriginalNode);


                    if (!isValidSave) {
                        return false;


                    }
                    boolean isChildsSaved = false;
                    PersistentTransaction t = null;


                    try {
                        t = TestisDbPersistentManager.instance().
                                getSession().beginTransaction();
                        TestDesignTreeNode originalNodeTestPlan = getTestPlanOfNode(originalNode);
                        changeNodesOriginalNode = null;


                        int indexOfChangeNode = 0;


                        for (int i = 0; i
                                < changeNodes.size(); i++) {
                            TestDesignTreeNode tempNodeTestPlan = getTestPlanOfNode((TestDesignTreeNode) changeNodes.get(i).getUserObject());



                            if (tempNodeTestPlan.getReference().getId() == originalNodeTestPlan.getReference().getId()) {
                                indexOfChangeNode = i;
                                changeNodesOriginalNode = (TestDesignTreeNode) changeNodes.get(i).getUserObject();


                                break;


                            }
                        }
                        if (changeNodesOriginalNode != null) {
                            changeNodesOriginalNode.convertToOriginal(originalNode.getReference());
                            DesignPart objectCopy = originalNode.getObject().createRefinedDatabaseCopy();


                            int elementId = objectCopy.getId();
                            changeNodesOriginalNode.getReference().getTreeReference().setElementId(elementId);
                            changeNodesOriginalNode.setObject(objectCopy);
                            changeNodesOriginalNode.getReference().getTreeReference().save();
                            changeNodesOriginalNode = TestDesignTreeNode.getNode(changeNodesOriginalNode.getReference(), objectCopy);
                            changeNodes.remove(indexOfChangeNode);


                            for (int i = 0; i
                                    < changeNodes.size(); i++) {
                                TestDesignTreeNode tmp = (TestDesignTreeNode) changeNodes.get(i).getUserObject();
                                tmp.getReference().getTreeReference().setClone(
                                        changeNodesOriginalNode.getReference().getTreeReference());
                                tmp.getReference().getTreeReference().save();
                                tmp = TestDesignTreeNode.getNode(tmp.getReference(), objectCopy);



                            }
                        } else {//all other clones must be original. because they are on other test plans
                            for (int i = 0; i
                                    < changeNodes.size(); i++) {
                                TestDesignTreeNode changeNode = (TestDesignTreeNode) changeNodes.get(i).getUserObject();
                                changeNode.convertToOriginal(originalNode.getReference());
                                DesignPart objectCopy = originalNode.getObject().createRefinedDatabaseCopy();


                                int elementId = objectCopy.getReference().getId();
                                changeNode.getReference().getTreeReference().setElementId(elementId);
                                changeNode.setObject(objectCopy);
                                changeNode.getReference().getTreeReference().save();
                                changeNode = TestDesignTreeNode.getNode(changeNode.getReference(), objectCopy);


                            }
                        }
                        t.commit();
                        isChildsSaved = true;


                    } catch (Exception ex) {
                        if (t != null) {
                            try {
                                t.rollback();


                            } catch (PersistentException ex1) {
                                ex1.printStackTrace();


                            }
                        }
                        ex.printStackTrace();


                    }
                    if (isChildsSaved) {
                        if (changeNodesOriginalNode != null) {
                            return controller.operationSave(params,
                                    changeNodesOriginalNode,
                                    false);


                        } else {//all other clones must be original. because they are on other test plans
                            for (int i = 0; i
                                    < changeNodes.size(); i++) {
                                TestDesignTreeNode changeNode = (TestDesignTreeNode) changeNodes.get(i).getUserObject();


                                if (!controller.operationSave(params,
                                        changeNode,
                                        false)) {
                                    return false;


                                }

                            }
                            return true;


                        }
                    }
                }
            }
        } finally {
            setSelected(null);
            setNotSelected(
                    null);


        }
        return true;


    }

    public void operationHideTab(Integer tab) {
        setModelProperty(HIDE_TAB,
                tab);


    }

    synchronized public void operationPasteCut(TestDesignTreeNode cutNode, MyDefaultMutableTreeNode parentNode) throws PersistentException {
        operationHandlePasteCut(cutNode,
                parentNode);
    }

    synchronized public void operationPasteCopy(TestDesignTreeNode copyObject,
            MyDefaultMutableTreeNode parentNode,
            boolean oneToOneCopy, boolean processSelectedObjects) throws PersistentException {
        operationHandlePasteCopy(copyObject,
                parentNode,
                oneToOneCopy,
                processSelectedObjects);


    }

    synchronized private boolean operationPasteCopyInternal(
            TestDesignTreeNode copyObject,
            TestDesignTreeNode parentTreeNode,
            boolean oneToOneCopy,
            OperationResultObject result,
            int childIndex, boolean processSelectedObjects) throws PersistentException {
        if (!copyObject.isSelected() && processSelectedObjects) {
            return true;


        }
        if (isDataObjectCloneAllowed(copyObject,
                parentTreeNode)) {
            TestDesignTreeNode newCopyNode;


            if (copyObject.isClone() && oneToOneCopy) {
                newCopyNode = TestDesign.newInstance().operationPasteClone(copyObject,
                        parentTreeNode, childIndex);
                if (newCopyNode != null) {
                    cloneIdsOfOriginals.put(Integer.valueOf(copyObject.getReference().getOriginalTreeReference().getId()), Integer.valueOf(newCopyNode.getId()));
                }

            } else {
                newCopyNode = TestDesign.newInstance().operationPasteCopy(copyObject,
                        parentTreeNode, childIndex);
                if (newCopyNode != null && oneToOneCopy) {
                    newIdsOfOriginals.put(copyObject.getId(), newCopyNode.getId());
                }

            }

            if (newCopyNode == null) {
                System.out.println(" --- COPY OPERATION --- ");
                System.out.print(" Source: " + newCopyNode);
                System.out.print(" Target: " + parentTreeNode);
                System.out.println(" COPY FAILED!");
                result.setResult(false);
                return false;
            }

            TestDesignTreeNode[] childNodes = copyObject.getChildren();


            int childCount = childNodes.length;
            LinkedList<TestDesignTreeNode> childsToBeCopied = new LinkedList<TestDesignTreeNode>();


            if (processSelectedObjects) {
                for (int i = 0; i
                        < childCount; i++) {
                    if (childNodes[i].isSelected()) {
                        childsToBeCopied.add(childNodes[i]);


                    }
                }
            } else {
                childsToBeCopied.addAll(copyObject.getChildrenLinkedList());


            }

            childCount = childsToBeCopied.size();


            for (int i = 0; i
                    < childCount; i++) {
                if (!operationPasteCopyInternal(childsToBeCopied.get(i),
                        newCopyNode, oneToOneCopy,
                        result, i, processSelectedObjects)) {
                    System.out.println("COPY FAILED!");
                    result.setResult(false);


                    return false;


                }
            }
            return true;


        } else {
            result.setResult(false);


            return false;


        }
    }

    private boolean isDataObjectCloneAllowed(TestDesignTreeNode source,
            TestDesignTreeNode target) {
        if (source == null || target == null
                || !(source.getObject() instanceof DataObjectRefined)) {
            return true;


        }

        String sourceModulType = TestDesign.getTestStepModuleTypeName(source.getReference());
        String sourceActionName = TestDesign.getTestStepActionName(source.getReference());
        String destinationModulType = TestDesign.getTestStepModuleTypeName(target.getReference());
        String destinationActionName = TestDesign.getTestStepActionName(target.getReference());

        if (sourceModulType.equals("WebAutomationModule")
                && !sourceActionName.equals("HandleDutIp")
                && !sourceActionName.equals("DefaultValueVerification")
                && !sourceActionName.equals("LanguageSelection")
                && !sourceActionName.equals("PageContentVerification")) {
            if (destinationModulType.equals("WebAutomationModule")
                    && !destinationActionName.equals("HandleDutIp")
                    && !destinationActionName.equals("DefaultValueVerification")
                    && !destinationActionName.equals("LanguageSelection")
                    && !destinationActionName.equals("PageContentVerification")) {

                return areKeysCompatibleWithDut(source,
                        target);


            } else {
                operationGenerateErrorMessage(
                        "Source Test Step of the selected Data Object is not compatible with Destination Test Step",
                        "Error");


                return false;


            }
        } else {
            if (destinationModulType.equals("WebAutomationModule")
                    && !destinationActionName.equals("HandleDutIp")
                    && !destinationActionName.equals("DefaultValueVerification")
                    && !destinationActionName.equals("LanguageSelection")
                    && !destinationActionName.equals("PageContentVerification")) {
                operationGenerateErrorMessage(
                        "Source Test Step of the selected Data Object is not compatible with Destination Test Step",
                        "Error");


                return false;


            } else {
                return areKeyNamesValid(source,
                        target);
            }
        }
    }

    private boolean areKeyNamesValid(TestDesignTreeNode source,
            TestDesignTreeNode target) {
        DataObjectRefined dataObject = (DataObjectRefined) source.getObject();
        String[] supportedKeys = TestDesign.getTestStepKeys(target.getReference());
        Iterator<String> it = dataObject.getKeyValueHashMap().keySet().iterator();
        boolean isKeysSupported = true;
        while (it.hasNext()) {
            String searchKey = it.next();
            boolean isFound = false;
            for (int i = 0; i
                    < supportedKeys.length; i++) {
                if (supportedKeys[i].equals(searchKey)) {
                    isFound = true;
                    break;
                }
            }
            if (!isFound) {
                System.out.println("The given key '" + searchKey + "' does not supported with the modul...");
                isKeysSupported = true;
            }
        }
        return isKeysSupported;
    }

    private boolean areKeysCompatibleWithDut(TestDesignTreeNode source,
            TestDesignTreeNode target) {
        DataObjectRefined dataObject = (DataObjectRefined) source.getObject();
        LinkedHashMap<String, String> hmap = dataObject.getKeyValueHashMap();
        DynamicMapDesignTreeNode rootNode = null;


        try {
            rootNode = DynamicMap.newInstance().getDynamicMapDesignTreeFomDB(false, target.getActiveDut().getId());


        } catch (PersistentException ex) {
            System.out.println("Exception occured when getting dynamic map -> " + ex.getMessage());


        }
        if (rootNode == null) {
            return true;


        }
        Iterator<String> it = hmap.keySet().iterator();


        boolean isOk = true;
        String abstractId;


        while (it.hasNext()) {
            abstractId = it.next();


            if (rootNode.searchObject("AbstractId", abstractId) == null) {
                System.out.println("RootNode:" + rootNode.getName() + " following abstractid does not exist:" + abstractId);
                isOk = true;


            }
        }
        return isOk;


    }

    synchronized public void operationPasteClone(TestDesignTreeNode cloneObject,
            MyDefaultMutableTreeNode parentNode,
            boolean processSelectedObjects) {
        operationHandlePasteClone(cloneObject,
                parentNode, processSelectedObjects);


    }

    synchronized private boolean operationPasteCloneInternal(
            TestDesignTreeNode cloneObject,
            TestDesignTreeNode parentTreeNode,
            OperationResultObject result, int childIndex, boolean processSelectedObjects) throws PersistentException {
        if (!cloneObject.isSelected() && processSelectedObjects) {
            return true;


        }
        if (isDataObjectCloneAllowed(cloneObject,
                parentTreeNode)) {
            TestDesignTreeNode newCloneNode = TestDesign.newInstance().operationPasteClone(cloneObject,
                    parentTreeNode, childIndex);


            if (newCloneNode == null) {
                System.out.println(" --- CLONE OPERATION --- ");
                System.out.print(" Source: " + newCloneNode);
                System.out.print(" Target: " + parentTreeNode);
                System.out.println(" CLONE FAILED!");
                result.setResult(false);


                return false;


            }

            TestDesignTreeNode[] childNodes = cloneObject.getChildren();


            int childCount = childNodes.length;
            LinkedList<TestDesignTreeNode> childsToBeCopied = new LinkedList<TestDesignTreeNode>();


            if (processSelectedObjects) {
                for (int i = 0; i
                        < childCount; i++) {
                    if (childNodes[i].isSelected()) {
                        childsToBeCopied.add(childNodes[i]);


                    }
                }
            } else {
                childsToBeCopied.addAll(cloneObject.getChildrenLinkedList());


            }

            childCount = childsToBeCopied.size();


            for (int i = 0; i
                    < childCount; i++) {
                if (!operationPasteCloneInternal(childsToBeCopied.get(i),
                        newCloneNode,
                        result, i, processSelectedObjects)) {
                    System.out.println("CLONE FAILED!");
                    result.setResult(false);


                    return false;


                }
            }
            return true;


        } else {
            result.setResult(false);


            return false;


        }
    }

    synchronized public void runTestSuite() {
        LinkedList<MyDefaultMutableTreeNode> nodesToExecute =
                new LinkedList<MyDefaultMutableTreeNode>();
        MyDefaultMutableTreeNode selectedNode;
        TestDesignTreeNode selectedTree;
        selectedNode =
                getSelectedMutableTreeNode();


        if (selectedNode != null) {
            selectedTree = (TestDesignTreeNode) selectedNode.getUserObject();


            while (!(selectedTree.getObject() instanceof TestSuiteRefined)) {
                selectedNode = selectedNode.getParent();
                selectedTree =
                        (TestDesignTreeNode) selectedNode.getUserObject();


            }
            for (int i = 0; i
                    < selectedNode.getParent().getChildCount(); i++) {
                if (selectedNode.getParent().getChildAt(i).isSelected()) {
                    nodesToExecute.add(selectedNode.getParent().getChildAt(i));


                }
            }
            TestDesignControllerList.newInstance().getRunningTestSuiteController().
                    operationRunTestSuite(nodesToExecute);


        }
    }

    public void operationLoadTreeFromDb(String name) {
        Timer t = new Timer();
        t.reset();
        TestDesignTreeNode root = null;
        MyDefaultMutableTreeNode node = removeLoadedSuiteByName(name);
        if (node != null) {
            this.operationCloseTree(node);
        }
        root = TestDesign.newInstance().getTestDesignTreeByName(false,
                name);
        if (root != null) {
            operationLoadTree(new MyDefaultMutableTreeNode(root,
                    true));
            operationRefreshTree();
        }
        t.print(name + " test design tree loaded  in ms:");
    }

    public String[] getLoadedTrees() {
        LinkedList<MyDefaultMutableTreeNode> list =
                (LinkedList<MyDefaultMutableTreeNode>) getModelProperty(TREE_LOAD);
        String[] result = new String[list.size()];
        for (int i = 0; i
                < list.size(); i++) {
            TestDesignTreeNode temp = (TestDesignTreeNode) list.get(i).getUserObject();
            if (temp != null) {
                result[i] = temp.getName();
            } else {
                System.out.println("NULL FOUND IN LOADED TEST LIST!");


            }
        }
        return result;


    }

    private MyDefaultMutableTreeNode removeLoadedSuiteByName(String name) {
        LinkedList<MyDefaultMutableTreeNode> list =
                (LinkedList<MyDefaultMutableTreeNode>) getModelProperty(TREE_LOAD);


        for (int i = 0; i
                < list.size(); i++) {
            TestDesignTreeNode node = (TestDesignTreeNode) list.get(i).
                    getUserObject();


            if (node != null) {
                TestSuiteRefined suite = (TestSuiteRefined) node.getObject();


                if (suite != null && suite.getName().equals(name)) {
                    return list.remove(i);


                }
            }
        }
        return null;


    }

    public void operationCloseTree() {
        operationCloseTree(getSelectedMutableTreeNode());


    }

    public void operationCloseTree(MyDefaultMutableTreeNode selectedNode) {
        MyDefaultMutableTreeNode parentNode = selectedNode.getParent();
        TestDesignTreeNode node =
                (TestDesignTreeNode) selectedNode.getUserObject();
        removeLoadedSuiteByName(
                node.getName());


        if (parentNode != null) {
            parentNode.remove(selectedNode);
            selectedNode =
                    null;
            operationRefreshTree();


        }
    }

    /**
     * Change the text element string in the model
     * @param newText The new text element string
     */
    synchronized public void operationLoadTree(MyDefaultMutableTreeNode tree) {
        setModelProperty(TREE_LOAD, tree);


    }

    synchronized public void operationSaveTree(MyDefaultMutableTreeNode tree) {
        setModelProperty(TREE_SAVE, tree);


    }

    private void setProperties(String value) {
        setModelProperty(SHOW_PROPERTIES, value);


    }

    private void setDesignPart(MyDefaultMutableTreeNode node) {
        setModelProperty(SELECT_DESIGN_PART,
                node);


    }

    synchronized public void operationSelectDesignPart(
            MyDefaultMutableTreeNode node,
            int selectMode) {
        setDesignPart(node);


        if (node != null && node.getUserObject() != null
                && node.getUserObject() instanceof TestDesignTreeNode) {
            setProperties(node.getUserObject().toString());


        } else {
            setProperties("");


        }
        if (selectMode == 1 && node != null) {
            node.setColor(MyDefaultMutableTreeNode.COMPARE);


            if (!isSourceSelected()) {
                operationSetSource(node);
                setSourceSelected(
                        true);


            } else {
                operationSetDestination(node);
                MyDefaultMutableTreeNode source = operationGetSource();
                MyDefaultMutableTreeNode destination = operationGetDestination();
                compare(
                        source,
                        destination);
                operationSelectCompareMode(
                        false);
                operationRefreshTree();


            }
        }
    }

    public void operationSelectCompareMode(Boolean mode) {
        if (!mode) {
            MyDefaultMutableTreeNode source = operationGetSource();
            MyDefaultMutableTreeNode destination = operationGetDestination();


            if (source != null) {
                source.setColor(MyDefaultMutableTreeNode.DEFAULT);


            }
            if (destination != null) {
                destination.setColor(MyDefaultMutableTreeNode.DEFAULT);


            }
            setSourceSelected(false);


        }
        setModelProperty(COMPARE_MODE_ON,
                mode);


    }

    private void operationSetSource(MyDefaultMutableTreeNode src) {
        setModelProperty(SOURCE,
                src);


    }

    private MyDefaultMutableTreeNode operationGetSource() {
        return (MyDefaultMutableTreeNode) getModelProperty(SOURCE);


    }

    private MyDefaultMutableTreeNode operationGetDestination() {
        return (MyDefaultMutableTreeNode) getModelProperty(DESTINATION);


    }

    private void operationSetDestination(MyDefaultMutableTreeNode dst) {
        setModelProperty(DESTINATION,
                dst);


    }

    synchronized private void compare(MyDefaultMutableTreeNode src,
            MyDefaultMutableTreeNode dst) {
        try {
            TestDesignControllerList.newInstance().getCompareGUIController().
                    start(
                    src,
                    dst,
                    this);


        } catch (Exception ex) {
        }
    }

    @Override
    synchronized public boolean executeOperation(Operation operation) {
        MyDefaultMutableTreeNode selectedNode;
        MyDefaultMutableTreeNode selectedParentNode;
        MyDefaultMutableTreeNode destinationGuiNode;


        if (operation.getSource().getUserObject() instanceof TestDesignTreeNode
                && operation.getDestination().getUserObject() instanceof TestDesignTreeNode) {
            TestDesignTreeNode source = (TestDesignTreeNode) operation.getSource().
                    getUserObject();
            destinationGuiNode =
                    operation.getDestination();


            if (operation.getOperation().equals(Operation.COPY)) {
                if (operation.isReplace()) {
                    try {
                        operationHandlePasteCopy(source, destinationGuiNode.getParent(), false, false);
                        return true;
                    } catch (PersistentException ex) {
                        ex.printStackTrace();


                        return false;


                    }
                } else {
                    try {
                        operationHandlePasteCopy(source, destinationGuiNode, false, false);


                        return true;


                    } catch (PersistentException ex) {
                        ex.printStackTrace();


                        return false;


                    }

                }


            } else if (operation.getOperation().equals(Operation.CLONE)) {
                if (operation.isReplace()) {
                    operationHandlePasteClone(source,
                            destinationGuiNode.getParent(), false);


                } else {
                    operationHandlePasteClone(source,
                            destinationGuiNode, false);


                    return true;


                }


            } else {
                System.out.println("UNKNOWN OPERATION");


                return false;


            }
            selectedNode = getSelectedMutableTreeNode();
            selectedParentNode =
                    selectedNode.getParent();


            int index = selectedParentNode.getIndex(destinationGuiNode);


            if (index + 1 == selectedParentNode.getIndex(selectedNode)) {
                operationHandleDelete(destinationGuiNode);


                return true;


            } else if (moveObject(null,
                    null,
                    destinationGuiNode,
                    destinationGuiNode.getNextSibling(),
                    selectedNode)) {
                operationHandleDelete(destinationGuiNode);
                selectedNode.removeFromParent();
                selectedParentNode.insert(selectedNode,
                        index);


                return true;


            }
        }
        return false;


    }

    synchronized public void operationDeleteTreeNode(
            MyDefaultMutableTreeNode thisNode) {
        operationHandleDelete(thisNode);


    }

    synchronized private void validateIntegrity(TestDesignTreeNode treeNode) {
        if (treeNode == null) {
            return;


        }
        if (treeNode.getReference().getTreeReference() != null
                && treeNode.getReference().getTreeReference().t_test_designtree != null
                && treeNode.getReference().getTreeReference().t_test_designtree.size() > 0) {
            if (!(treeNode.getChildren() != null
                    && treeNode.getChildren().length
                    == treeNode.getReference().getTreeReference().t_test_designtree.size())) {
                TestDesign.newInstance().fixChildren(treeNode);
                TestDesignTreeNode[] childNode = treeNode.getChildren();


                for (int i = 0; i
                        < childNode.length; i++) {
                    validateIntegrity(childNode[i]);


                }
            }
        }
    }

    synchronized public boolean operationDeleteTreeNodeInternal(
            TestDesignTreeNode node,
            OperationResultObject result) {
        if (node == null) {
            result.setResult(false);


            return false;


        }
        T_test_designtree[] childNodes =
                node.getReference().getTreeReference().t_test_designtree.toArray();
        int max = childNodes.length;
    
        validateIntegrity(node);

        for (int i = max - 1; i >= 0; i--) {
            TestDesignTreeRefined ref=TestDesignTreeRefined.getDesignTree(childNodes[i]);
            operationDeleteTreeNodeInternal(TestDesignTreeNode.getNode(ref),
                    result);
        }

        if (node != null) {
            if (node.getObject() instanceof TestSuiteRefined) {
                removeLoadedSuiteByName(node.getObject().getName());


            }
            if (node.delete()) {
                node = null;
                return true;
            } else {
                result.setResult(false);
                System.out.println("FAILED to delete node with id:"
                        + node.getId());
            }
        }
        //result.setResult(false);
        return false;


    }

    public DesignPart operationGetSelectedDesignPart() {
        if (getSelectedTreeNode() != null) {
            return getSelectedTreeNode().getObject();


        } else {
            return null;


        }
    }

    public TestDesignTreeNode getSelectedTreeNode() {
        MyDefaultMutableTreeNode selectedNode = getSelectedMutableTreeNode();


        if (selectedNode != null) {
            if (selectedNode.getUserObject() != null
                    && selectedNode.getUserObject() instanceof TestDesignTreeNode) {
                return (TestDesignTreeNode) selectedNode.getUserObject();


            }
        }
        return null;


    }

    public MyDefaultMutableTreeNode getSelectedMutableTreeNode() {
        return (MyDefaultMutableTreeNode) getModelProperty(SELECT_DESIGN_PART);


    }

    synchronized public void moveObject(TestDesignTreeNode currentNode,
            TestDesignTreeNode newNextNode) {
        TestDesignTreeNode parent = currentNode.getParent();


        for (int i = 0; i
                < parent.getChildrenLinkedList().size(); i++) {
            if (parent.getChild(i).getId() == currentNode.getId()) {
                Object obj = parent.getChildrenLinkedList().remove(i);


                if (newNextNode != null) {
                    for (int j = 0; j
                            < parent.getChildrenLinkedList().size();
                            j++) {
                        if ((parent.getChild(j)).getId() == newNextNode.getId()) {
                            parent.addChild(j, (TestDesignTreeNode) obj);


                            return;


                        }
                    }
                } else {
                    parent.addChild((TestDesignTreeNode) obj);


                }
            }
        }
    }

    @Override
    synchronized public boolean moveObject(
            MyDefaultMutableTreeNode currentPrevNode,
            MyDefaultMutableTreeNode currentNextNode,
            MyDefaultMutableTreeNode newPrevNode,
            MyDefaultMutableTreeNode newNextNode,
            MyDefaultMutableTreeNode currentNode) {
        TestDesignTreeNode currentPrevTreeNode = null;
        TestDesignTreeNode currentNextTreeNode = null;
        TestDesignTreeNode newPrevTreeNode = null;
        TestDesignTreeNode newNextTreeNode = null;
        TestDesignTreeNode currentTreeNode = null;



        if (currentNode == null) {
            return false;


        } else {
            currentTreeNode = (TestDesignTreeNode) currentNode.getUserObject();


        }


        if (currentPrevNode != null) {
            currentPrevTreeNode = (TestDesignTreeNode) currentPrevNode.getUserObject();


        }
        if (currentTreeNode.getObject() instanceof PreConditionCaseRefined
                || currentTreeNode.getObject() instanceof PostConditionCaseRefined
                || currentTreeNode.getObject() instanceof TestSuiteRefined) {
            return false;


        }
        if (newNextNode != null) {
            if (((TestDesignTreeNode) newNextNode.getUserObject()).getObject() instanceof PreConditionCaseRefined) {
                return false;


            } else {
                newNextTreeNode =
                        (TestDesignTreeNode) newNextNode.getUserObject();


            }


        }
        if (newPrevNode != null) {
            if (((TestDesignTreeNode) newPrevNode.getUserObject()).getObject() instanceof PostConditionCaseRefined) {
                return false;


            } else {
                newPrevTreeNode =
                        (TestDesignTreeNode) newPrevNode.getUserObject();


            }


        }
        if (currentNextNode != null) {
            currentNextTreeNode = (TestDesignTreeNode) currentNextNode.getUserObject();


        }


        if (TestDesign.newInstance().handleMoveObjectRanks(currentPrevTreeNode,
                currentNextTreeNode,
                newPrevTreeNode,
                newNextTreeNode,
                currentTreeNode)) {
            moveObject(currentTreeNode,
                    newNextTreeNode);


            return true;


        } else {
            return false;


        }
    }

    public void operationGenerateErrorMessage(String message,
            String title) {
        TreeViewPanel.showMessageDialog(message,
                title);


    }

    public boolean operationShowConfirmDialogBox(String message,
            String title) {
        return TreeViewPanel.showConfirmDialogBox(message,
                title);


    }

    @Override
    public MyDefaultMutableTreeNode[] getNotSelected() {
        return m_notSelected;
    }

    @Override
    public void setNotSelected(MyDefaultMutableTreeNode[] notSelected) {
        m_notSelected = notSelected;


    }

    private boolean isSourceSelected() {
        return m_sourceSelected;


    }

    private void setSourceSelected(boolean sourceSelected) {
        m_sourceSelected = sourceSelected;


    }

    public TestDesignTreeNode constructRunTree(
            MyDefaultMutableTreeNode child,
            TestDesignTreeNode parent) {
        TestDesignTreeNode toBeCloned =
                (TestDesignTreeNode) child.getUserObject();

        TestDesignTreeNode addNode =
                TestDesignTreeNode.createNode(toBeCloned.getReference(),
                toBeCloned.getObject());


        for (int i = 0; i
                < child.getChildCount(); i++) {
            if (child.getChildAt(i).isSelected()) {
                constructRunTree(child.getChildAt(i),
                        addNode);


            }
        }
        if (parent == null) {

            return addNode;


        } else {
            parent.addChild(addNode);


            return parent;


        }
    }

    public TestDesignTreeNode constructTree(
            MyDefaultMutableTreeNode child,
            TestDesignTreeNode parent) {
        TestDesignTreeNode toBeCloned =
                (TestDesignTreeNode) child.getUserObject();
        TestDesignTreeNode addNode =
                TestDesignTreeNode.getNode(toBeCloned.getReference(),
                toBeCloned.getObject());


        for (int i = 0; i
                < child.getChildCount(); i++) {
            if (child.getChildAt(i).isSelected()) {
                constructTree(child.getChildAt(i),
                        addNode);


            }
        }
        if (parent == null) {
            return addNode;


        } else {
            parent.addChild(addNode);


            return parent;


        }
    }

    public void operationClearSelection() {
        setModelProperty(CLEAR_SELECTION_PROPERTY, Boolean.TRUE);

    }

    public void operationValidateTree() {
        TestDesignTreeNode root = getSelectedTreeNode();
        root.validateTree(root);
        operationExpandToNextNode();

    }

    public void operationExpandToNextNode() {
        if (m_lastSearchValue.isEmpty()) {
            operationExpandToNextInvalidNode();
        } else {
            operationFindNextNodeByText();
        }
    }

    public void operationExpandToNextInvalidNode() {
        try {
            MyDefaultMutableTreeNode node = getNextInvalidNode(getSelectedMutableTreeNode());
            if (node != null) {
                setDesignPart(node);
                setModelProperty(RELOAD_TREE_PATH, new TreePath(node.getPath()));
            }
        } catch (StackOverflowError ex) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Too many nodes to search...",
                    "ERROR");
        }
    }

    private MyDefaultMutableTreeNode getNextInvalidNode(MyDefaultMutableTreeNode mnode) {
        if (mnode == null) {
            return null;
        }
        TestDesignTreeNode node = (TestDesignTreeNode) mnode.getUserObject();
        if (!node.isValid() && mnode != getSelectedMutableTreeNode()) {
            return mnode;
        }
        int childCount = mnode.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                return getNextInvalidNode(mnode.getChildAt(i));
            }
        } else {
            while (mnode.getNextSibling() == null) {
                mnode = mnode.getParent();
                if (mnode == null) {
                    return null;
                }
            }
            return getNextInvalidNode(mnode.getNextSibling());
        }
        return null;
    }

    public void operationFindNextNodeByText() {
        try {
            MyDefaultMutableTreeNode node = getNextNodeContainsValue(getSelectedMutableTreeNode());
            if (node != null) {
                setDesignPart(node);
                setModelProperty(RELOAD_TREE_PATH, new TreePath(node.getPath()));
            }
        } catch (StackOverflowError ex) {
            TestDesignControllerList.newInstance().getTreeController().
                    operationGenerateErrorMessage("Too many nodes to search...",
                    "ERROR");
        }
    }

    private MyDefaultMutableTreeNode getNextNodeContainsValue(MyDefaultMutableTreeNode mnode) {
        if (mnode == null) {
            return null;
        }
        TestDesignTreeNode node = (TestDesignTreeNode) mnode.getUserObject();
        if (node.getName().toUpperCase().contains(m_lastSearchValue.toUpperCase()) && mnode != getSelectedMutableTreeNode()) {
            return mnode;
        } else if (StringVerification.verifyText(m_lastSearchValue, node.getName()) && mnode != getSelectedMutableTreeNode()) {
            return mnode;
        } else if (node.getTypeName().equals("DataObject")) {
            DataObjectRefined dataObject = (DataObjectRefined) node.getObject();
            LinkedHashMap<String, String> map = dataObject.getKeyValueHashMap();
            if (map.size() > 0) {
                Set<String> keySet = map.keySet();
                Iterator<String> it = keySet.iterator();
                while (it.hasNext()) {
                    String searchKey = it.next();
                    String value = map.get(searchKey);
                    if (value.toUpperCase().contains(m_lastSearchValue.toUpperCase()) && mnode != getSelectedMutableTreeNode()) {
                        return mnode;
                    } else if (StringVerification.verifyText(m_lastSearchValue, value) && mnode != getSelectedMutableTreeNode()) {
                        return mnode;
                    } else if (searchKey.contains(m_lastSearchValue) && mnode != getSelectedMutableTreeNode()) {
                        return mnode;
                    } else if (StringVerification.verifyText(m_lastSearchValue, searchKey) && mnode != getSelectedMutableTreeNode()) {
                        return mnode;
                    }
                }
            }
        }
        int childCount = mnode.getChildCount();
        if (childCount > 0) {
            for (int i = 0; i < childCount; i++) {
                return getNextNodeContainsValue(mnode.getChildAt(i));
            }
        } else {
            while (mnode.getNextSibling() == null) {
                mnode = mnode.getParent();
                if (mnode == null) {
                    return null;
                }
            }
            return getNextNodeContainsValue(mnode.getNextSibling());
        }
        return null;
    }
}
